﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using External.Controls.Helpers;
using External.Controls.Interfaces;
using External.Controls.ModelViews;

namespace External.Controls.Controls
{
    public class HallCanvas : Canvas
    {
        public HallCanvas()
        {
            Background = Brushes.SeaShell;

            Binding binding = new Binding();
            binding.Source = this;
            binding.Path = new PropertyPath("SelectedScheme.Geometries");
            binding.BindsDirectlyToSource = true;
            SetBinding(ItemSourceProperty, binding);

            NavigationCommand = new NavigationCommand(this);
        }

        /// <summary>
        /// Команда навигации
        /// </summary>
        public ICommand NavigationCommand { get; set; }

        public static readonly DependencyProperty SelectedSchemeProperty =
            DependencyProperty.Register("SelectedScheme", typeof(IDrawableScheme), typeof(HallCanvas), new PropertyMetadata(null));

        public IDrawableScheme SelectedScheme
        {
            get
            {
                return (IDrawableScheme)GetValue(SelectedSchemeProperty);
            }
            set
            {
                SetValue(SelectedSchemeProperty, value);
            }
        }
        
        public static readonly DependencyProperty IsEditProperty =
            DependencyProperty.Register("IsEdit", typeof (bool), typeof (HallCanvas), new PropertyMetadata(default(bool)));

        public bool IsEdit
        {
            get { return (bool) GetValue(IsEditProperty); }
            set { SetValue(IsEditProperty, value); }
        }

        public static readonly DependencyProperty ItemSourceProperty =
            DependencyProperty.Register("ItemSource", typeof(IList<FrameworkElement>), typeof(HallCanvas), new PropertyMetadata(OnItemSourceChanged));

        /// <summary>
        /// Элементы\фигуры на канве
        /// </summary>
        public IList<FrameworkElement> ItemSource
        {
            get { return (IList<FrameworkElement>)GetValue(ItemSourceProperty); }
            set { SetValue(ItemSourceProperty, value); }
        }

        private static void OnItemSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            HallCanvas control = (HallCanvas) d;
            control.ItemSourceChanged((IList<FrameworkElement>)e.OldValue, (IList<FrameworkElement>)e.NewValue);
        }

        private void ItemSourceChanged(IList<FrameworkElement> oldValue, IList<FrameworkElement> newValue)
        {
            foreach (var item in Children.OfType<DesignerItem>())
                item.Content = null;

            Children.Clear();
            
            //odlValue на случай если надо будет от чего нить отписаться

            //Заменяем на новые контролы
            foreach (var designerItem in newValue)
                Children.Add(designerItem);
        }

        private Point? _rubberbandSelectionStartPoint = null;

        private SelectionService _selectionService;
        internal SelectionService SelectionService
        {
            get
            {
                if (_selectionService == null)
                    _selectionService = new SelectionService(this);

                return _selectionService;
            }
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Source == this)
            {
                // in case that this click is the start of a 
                // drag operation we cache the start point
                this._rubberbandSelectionStartPoint = new Point?(e.GetPosition(this));

                // if you click directly on the canvas all 
                // selected items are 'de-selected'
                SelectionService.ClearSelection();
                Focus();
                e.Handled = true;
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            // if mouse button is not pressed we have no drag operation, ...
            if (e.LeftButton != MouseButtonState.Pressed)
                this._rubberbandSelectionStartPoint = null;

            // ... but if mouse button is pressed and start
            // point value is set we do have one
            if (this._rubberbandSelectionStartPoint.HasValue)
            {
                // create rubberband adorner
                AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
                if (adornerLayer != null)
                {
                    RubberbandAdorner adorner = new RubberbandAdorner(this, _rubberbandSelectionStartPoint);
                    if (adorner != null)
                    {
                        adornerLayer.Add(adorner);
                    }
                }
            }
            e.Handled = false;
        }

        protected override Size MeasureOverride(Size constraint)
        {
            Size size = new Size();

            foreach (UIElement element in this.InternalChildren)
            {
                double left = Canvas.GetLeft(element);
                double top = Canvas.GetTop(element);
                left = double.IsNaN(left) ? 0 : left;
                top = double.IsNaN(top) ? 0 : top;

                //measure desired size for each child
                element.Measure(constraint);

                Size desiredSize = element.DesiredSize;
                if (!double.IsNaN(desiredSize.Width) && !double.IsNaN(desiredSize.Height))
                {
                    size.Width = Math.Max(size.Width, left + desiredSize.Width);
                    size.Height = Math.Max(size.Height, top + desiredSize.Height);
                }
            }
            // add margin 
            size.Width += 10;
            size.Height += 10;
            return size;
        }
    }
}